import axios from "axios"
import router from "../router"
import qs from "qs"
//加密算法
const sm2 = require("sm-crypto").sm2
const cipherMode = 0 // 1 - C1C3C2，0 - C1C2C3，默认为1
//控制返回状态
const validateStatus = (status) => {
  return status >= 200 && status < 300
}
axios.defaults.timeout = 6000
axios.defaults.withCredentials = true // 设置允许跨域设置cookie
// 开发环境下给定，生产环境删除
axios.defaults.baseURL = process.env.NODE_ENV === "production" ? "" : "/apis"

axios.defaults.validateStatus = validateStatus
axios.defaults.headers["Content-Type"] = "application/json"
axios.defaults.headers["x-requested-with"] = "XMLHttpRequest"

//控制接口短时间内不会被重复迪调用
const pending = new Map()
const addPending = (config) => {
  const url = [config.method, config.url, qs.stringify(config.data)].join("&")
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken((cancel) => {
      if (!pending.has(url)) {
        pending.set(url, cancel)
      }
    })
}
const removePending = (config) => {
  const url = [config.method, config.url, qs.stringify(config.data)].join("&")
  if (pending.has(url)) {
    const cancel = pending.get(url)
    cancel("请勿重复操作~")
    pending.delete(url)
  }
}
export const clearPending = () => {
  for (const [url, cancel] of pending) {
    cancel(url)
  }
  pending.clear()
}
// http request 拦截器
axios.interceptors.request.use(
  (config) => {
    config.headers.token = localStorage.getItem("TOKEN") || ""
    if (config.headers["Content-Type"] == "application/x-www-form-urlencoded") {
      config.data = qs.stringify(config.data)
    }
    if (config.data && config.data.publicKey) {
      //是否密文传输
      config.headers["Security-Key"] = localStorage.getItem("mypublicKey")
      config.headers["Security"] = true
      config.data = {
        strSecret: sm2.doEncrypt(
          JSON.stringify(config.data),
          localStorage.getItem("publicKey"),
          cipherMode
        )
      } //加密
    }
    //控制文件切片上传可以重复调用接口
    if (!config.url.startsWith("/system/file/affix")) {
      //发起请求时，取消掉当前正在进行的相同请求
      removePending(config)
      addPending(config)
    }
    return config
  },
  (err) => {
    err = "请求异常"
    return Promise.reject(err)
  }
)

// http request 拦截器
axios.interceptors.response.use(
  (resp) => {
    removePending(resp)
    const { code, msg } = resp.data
    if (code == "402") {
      //登陆超时重新登陆
      router.push("/login")
      return Promise.reject("登陆超时，请重新登陆~")
    }

    if (code == "401") {
      //token过期重新获取token调用之前的方法
      return axios
        .get(
          "sso/system/token/refresh" +
            "?refreshToken=" +
            localStorage.getItem("refreshToken")
        )
        .then((res) => {
          localStorage.setItem("TOKEN", res.data.data)
          return axios
            .request(resp.config)
            .then((resps) => {
              return resps
            })
            .catch((err) => {
              router.push("/login")
              return Promise.reject(err.msg)
            })
        })
    }
    if (!validateStatus(code) && code !== undefined) {
      //返回错误状态
      return Promise.reject(msg)
    }
    if (resp.data.security) {
      //是否密文传输
      resp.data.data = JSON.parse(
        sm2.doDecrypt(
          resp.data.data,
          localStorage.getItem("myprivateKey"),
          cipherMode
        )
      ) //解密
    }
    return resp
  },
  (err) => {
    if (err.msg) {
      err = err.msg
    }
    return Promise.reject(err)
  }
)

export default axios
